/**
 * 启动页
 */

import * as React from 'react';
import { View, Text, Linking } from 'react-native';
import { ClientRole } from 'react-native-agora';
import RNFS from 'react-native-fs';
import { unzip } from 'react-native-zip-archive';

import { modalOpen, modalClose, toolTipOpen } from '../../../../util/global';
import { DEBUG, isIOS } from '../../../../constant';
import styles from './style';
import FastImage from '../../../../components/FastImage';
import Log from '../../../../common/log';
import {
  clearUserInfo,
  getUserInfo,
  initUserInfo,
  setUserInfo
} from '../../../../store/user';
import { appStartUse } from '../../../../store/time';
import systemUtil from '../../../../util/native/systemUtil';
import { shellExec, splashScreen } from '../../../../util/native';
import { getLaunchImage } from '../../../../util/adaptIOS';
import { AppApi, LoginApi } from '../../../../api';
import { openView } from '../../../Login/actions';
import { initEngine } from '../../../../util/RTC/rtcEngine';
import { UserRole } from '../../../ClassRoom/constant';
import {
  setAppConfig,
  getAppConfigInfo,
  setIsOpenGuestEntry,
  getProblemWebview,
  setProblemWebview
} from '../../../../store/appConfig';
import { GetAppConfigRes } from '../../../../api/app/getAppConfig';
import {
  getPermission,
  openPermissionModal
} from '../../../../util/permission';
import { codePushUpdate } from '../../../../util/codepush';
import tracker from '../../../../util/actionTracker';
import { showLaunch } from '../../../../constant/events';
import { DOWNLOAD_HTML_PATH } from '../../../Login/constant';
import rnfsDownload from '../../../../util/videoDownload/rnfsDownload';
import customAwait from '../../../../util/customAwait';
import PortraitAlert from '../../../../components/Alert/PortraitAlert';

const TAG = 'Launch';
let timer: NodeJS.Timer | null = null;

class Launch extends React.Component {
  public async componentDidMount(): Promise<any> {
    splashScreen.hide();

    Log.i(
      TAG,
      JSON.stringify({
        versionCode: systemUtil.getVersionCode(),
        versionChannel: systemUtil.getVersionChannel()
      })
    );

    appStartUse();
    await initUserInfo();

    tracker.reportAction(showLaunch);

    await this.refreshToken();
    this.init();
  }

  // eslint-disable-next-line react/sort-comp
  public async refreshToken(): Promise<void> {
    const emptyPromise = new Promise<void>((resolve): void => {
      resolve();
    });

    const { token } = getUserInfo();
    if (!token) return emptyPromise;

    timer = setTimeout((): void => {
      modalOpen({
        Type: (): React.ReactElement => (
          <View style={styles.loading}>
            <Text style={styles.loadingDesc}>登录中...</Text>
          </View>
        )
      });
    }, 3 * 1000);

    const refreshTokenFail = (): void => {
      if (timer) {
        clearTimeout(timer);
      }
      modalClose();
      clearUserInfo();
    };

    try {
      const res = await LoginApi.refreshToken({
        token
      });
      clearTimeout(timer);
      modalClose();
      if (res.code === 0) {
        setUserInfo({ token: res.data.token, role: res.data.role });
        const { userId, role } = getUserInfo();
        initEngine({
          uid: Number(userId),
          role:
            role === UserRole.Student || role === UserRole.Assist
              ? ClientRole.Broadcaster
              : ClientRole.Audience
        });
        shellExec.makeSureLongLinkConnected();
      } else {
        refreshTokenFail();
        return emptyPromise;
      }
    } catch (e) {
      refreshTokenFail();
      return emptyPromise;
    }
  }

  // 通过浏览器下载最新安装包
  public downloadApk = (apkUrl: string): void => {
    const url = apkUrl;
    Linking.canOpenURL(url)
      .then((support): void => {
        if (!support) {
          toolTipOpen({ desc: '请去应用市场或者官网更新' });
          return;
        }
        Linking.openURL(url);
      })
      .catch((): void => {
        toolTipOpen({ desc: '请去应用市场或者官网更新' });
      });
  };

  // 打开版本更新弹框
  public openNewVersion = (apkUrl: string): void => {
    modalOpen({
      Type: (): React.ReactElement => (
        <PortraitAlert
          title="发现新版本"
          sureDesc="立即更新"
          subTitle="抱歉您使用的版本太旧啦，已无法继续使用。为保证您的使用体验，请立即更新版本"
          sureAction={(): void => this.downloadApk(apkUrl)}
        />
      ),
      needBack: true
    });
  };

  // 下载problemWebView文件
  public async downloadProblemHtml(
    newProblemWebviewName: string
  ): Promise<void> {
    const downloadProblemHtmlAction = async (): Promise<string> => {
      let isDownloadProblemHtmlSuccess = false;

      const DOWNLOAD_PROBLEM_HTML_ZIP_PATH = `${DOWNLOAD_HTML_PATH}/problem.zip`;
      const DOWNLOAD_PROBLEM_HTML_PATH = `${DOWNLOAD_HTML_PATH}/problem`;

      const isZipExist = await RNFS.exists(DOWNLOAD_PROBLEM_HTML_ZIP_PATH);
      const isHtmlExist = await RNFS.exists(DOWNLOAD_PROBLEM_HTML_PATH);

      // 设置互动题webview相关信息
      const {
        problemWebviewName: originProblemWebviewName
      } = getProblemWebview();
      // 如果problemWebview有更新或html文件不存在，则需要下载
      const needDownload =
        originProblemWebviewName !== newProblemWebviewName || !isHtmlExist;

      setProblemWebview({
        needDownload,
        problemWebviewName: newProblemWebviewName
      });

      const successPromise = new Promise<string>((resolve): void => {
        resolve('downloadProblemHtmlSuccess');
      });
      const failPromise = new Promise<string>((resolve, reject): void => {
        reject(new Error('downloadProblemHtmlFail'));
      });

      // 如果不需要下载，直接返回成功
      if (!needDownload) {
        return successPromise;
      }

      if (isZipExist) {
        await RNFS.unlink(DOWNLOAD_PROBLEM_HTML_ZIP_PATH);
      }
      if (isHtmlExist) {
        await RNFS.unlink(DOWNLOAD_PROBLEM_HTML_PATH);
      }

      const options = {
        fromUrl: DEBUG
          ? `http://resource.mifengxiaoban.com/webview/d/${newProblemWebviewName}.zip`
          : `http://resource.mifengxiaoban.com/webview/p/${newProblemWebviewName}.zip`,
        toFile: DOWNLOAD_PROBLEM_HTML_ZIP_PATH,
        background: true,
        connectionTimeout: 8000,
        readTimeout: 8000
      };

      const ret = await rnfsDownload(options);
      const [error, res] = await customAwait(ret.promise);

      if (error) {
        Log.i(
          TAG,
          JSON.stringify({
            event: 'problemHtmlDownloadFail',
            error
          })
        );
      }

      if (res) {
        const { statusCode } = res;
        if (statusCode === 200) {
          Log.i(
            TAG,
            JSON.stringify({
              event: 'problemHtmlDownloadSuccess',
              res
            })
          );
          // 解压
          const [unzipError, unzipRes] = await customAwait(
            unzip(DOWNLOAD_PROBLEM_HTML_ZIP_PATH, DOWNLOAD_PROBLEM_HTML_PATH)
          );
          if (unzipError) {
            Log.i(
              TAG,
              JSON.stringify({
                event: 'unzipProblemHtmlDownloadFail',
                error: unzipError
              })
            );
          }
          if (unzipRes) {
            // 下载webview成功
            isDownloadProblemHtmlSuccess = true;
            setProblemWebview({
              needDownload: false
            });
            Log.i(
              TAG,
              JSON.stringify({
                event: 'unzipProblemHtmlDownloadSuccess',
                res: unzipRes
              })
            );
          }
        } else {
          Log.i(
            TAG,
            JSON.stringify({
              event: 'problemHtmlDownloadFail',
              error,
              statusCode
            })
          );
        }
      }
      return isDownloadProblemHtmlSuccess ? successPromise : failPromise;
    };
    const emptyPromise = new Promise<void>((resolve): void => {
      resolve();
    });
    const [
      downloadProblemHtmlError,
      downloadProblemHtmlRes
    ] = await customAwait(downloadProblemHtmlAction());

    if (downloadProblemHtmlError) {
      toolTipOpen({
        desc: '课程相关资源加载失败，会影响上课体验'
      });
    }

    return emptyPromise;
  }

  // 初始化
  public init = (): void => {
    if (isIOS) {
      this.getAppConfig()
        .then((): void => {
          openView();
          codePushUpdate();
        })
        .catch((apkUrl): void => {
          this.openNewVersion(apkUrl);
        });
      return;
    }

    getPermission()
      .then((): void => {
        openView();
        this.getAppConfig()
          .then((): void => {
            codePushUpdate();
          })
          .catch((apkUrl): void => {
            this.openNewVersion(apkUrl);
          });
      })
      .catch((permissionsDesc): void => {
        openPermissionModal(permissionsDesc, (): void => {
          openView();
          this.getAppConfig()
            .then((): void => {
              codePushUpdate();
            })
            .catch((apkUrl): void => {
              this.openNewVersion(apkUrl);
            });
        });
      });
  };

  // 获取app配置: 1.壳版本; 2.审核状态
  public getAppConfig = (): Promise<any> => {
    return new Promise((resolve, reject): void => {
      const appVersion = systemUtil.getAppVersion();

      const checkVersion = (res: GetAppConfigRes): void => {
        const {
          minVer,
          invalidVers = [],
          openGuestEntry,
          apkUrl,
          problemWebviewName
        } = res.data;

        setIsOpenGuestEntry(openGuestEntry);
        this.downloadProblemHtml(problemWebviewName);

        const appVersions = appVersion.split('.');
        const minVers = minVer.split('.');
        const isInvalid = invalidVers.find(
          (item: string): boolean => item === appVersion
        );

        if (isInvalid) {
          reject(apkUrl);
        }
        if (appVersions.length !== 3 || minVers.length !== 3) {
          resolve();
        }
        if (appVersions[0] < minVers[0]) {
          reject(apkUrl);
        }
        if (appVersions[0] === minVers[0] && appVersions[1] < minVers[1]) {
          reject(apkUrl);
        }
        if (
          appVersions[0] === minVers[0] &&
          appVersions[1] === minVers[1] &&
          appVersions[2] < minVers[2]
        ) {
          reject(apkUrl);
        }

        resolve();
      };

      AppApi.getAppConfig({ osType: isIOS ? 'ios' : 'android' })
        .then((res): void => {
          if (res.code === 0) {
            setAppConfig(res);
            checkVersion(res);
          } else {
            const localAppConfig = getAppConfigInfo();
            if (localAppConfig) {
              checkVersion(localAppConfig);
            } else {
              Log.e(TAG, 'fail res.success');
            }
          }
        })
        .catch((msg): void => {
          const localAppConfig = getAppConfigInfo();
          if (localAppConfig) {
            checkVersion(localAppConfig);
          } else {
            Log.e(TAG, msg);
          }
        });
    });
  };

  public render(): React.ReactElement {
    return (
      <View style={styles.container}>
        <FastImage
          source={{
            uri: !isIOS ? 'launch' : getLaunchImage()
          }}
          style={styles.launch}
        />
      </View>
    );
  }
}

export default Launch;
